package com.msb.mall.thirdPart.utils;

import com.jcraft.jsch.*;
import com.msb.mall.thirdPart.constants.UploadConstants;
import com.msb.mall.thirdPart.vo.UploadFile;
import com.msb.mall.thirdPart.vo.UploadServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Base64;
import java.util.UUID;

/**
 * 文件上传到 搭建的虚拟机服务器
 */
@Slf4j
public class Upload2Server {

    /** todo: 文件上传到搭建的虚拟机 *********start*********** */
    /**
     * 直接接收前端上传的文件, 再上传服务器
     */
    public static void uploadToServerSimple(MultipartFile uploadFile, UploadServer uploadServer) throws Exception {
        try {
            JSch jsch = new JSch();
            // 根据用户名，主机ip，端口获取一个session对象
            Session session = jsch.getSession(uploadServer.getUser(), uploadServer.getHost(), uploadServer.getPort());
            session.setPassword("root");// 设置密码
            /**”如果设置成“yes”，ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件，
             并且一旦计算机的密匙发生了变化，就拒绝连接。 */
            session.setConfig("StrictHostKeyChecking", "no");

            // 设置超时时间  10s
            session.setTimeout(10000);
            // 建立连接
            session.connect();

            // 创建一个存放 正在使用的文件目录
            Channel channel0 = session.openChannel(UploadConstants.UPLOAD_EXEC);
            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel0).setCommand("mkdir -p /mydata/myfile/useFile");
            ((ChannelExec) channel0).setCommand("mkdir -p " + uploadServer.getUseFilePath());
            channel0.connect();
            channel0.disconnect();

            // 创建一个存放 正在使用的文件目录
            // 后面可直接执行删除命令处理，目前先熟悉各种操作
//            Channel channel1 = session.openChannel(UploadConstants.UPLOAD_EXEC);
//            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel1).setCommand("mkdir -p " + uploadServer.getNoUseFilePath());
//            channel0.connect();
//            channel0.disconnect();

            // 上传文件操作
            File file = convertMultipartFileToFile(uploadFile);
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[(int) file.length()];
            fis.read(buffer);
            fis.close();

            ChannelSftp channel = (ChannelSftp) session.openChannel(UploadConstants.UPLOAD_SFTP);
            channel.connect();
            channel.cd(uploadServer.getUseFilePath());
            channel.put(new ByteArrayInputStream(buffer), uploadFile.getOriginalFilename());
            channel.disconnect();

            // 断开连接
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上传linux服务器失败 >>>" + e.getMessage());
        }
    }

    /**
     * 将本地图片上传至 linux服务器
     */
    public static void uploadToServerOrigin(UploadServer uploadServer) throws Exception {
        try {
            JSch jsch = new JSch();
            // 根据用户名，主机ip，端口获取一个session对象
            Session session = jsch.getSession(uploadServer.getUser(), uploadServer.getHost(), uploadServer.getPort());
            session.setPassword("root");// 设置密码
            /**”如果设置成“yes”，ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件，
             并且一旦计算机的密匙发生了变化，就拒绝连接。 */
            session.setConfig("StrictHostKeyChecking", "no");
//        Properties config = new Properties();
//        config.put("StrictHostKeyChecking", "no");
//        session.setConfig(config);

            // 设置超时时间  10s
            session.setTimeout(10000);
            // 建立连接
            session.connect();

            // 创建一个存放 正在使用的文件目录
            Channel channel0 = session.openChannel(UploadConstants.UPLOAD_EXEC);
            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel0).setCommand("mkdir -p /mydata/myfile/useFile");
            ((ChannelExec) channel0).setCommand("mkdir -p " + uploadServer.getUseFilePath());
            channel0.connect();
            channel0.disconnect();

            // 创建一个存放 正在使用的文件目录
            // 后面可直接执行删除命令处理，目前先熟悉各种操作
//            Channel channel1 = session.openChannel(UploadConstants.UPLOAD_EXEC);
//            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel1).setCommand("mkdir -p /mydata/myfile/nouseFile");
//            channel0.connect();
//            channel0.disconnect();

            // 上传文件操作
            // 先用本地文件上传测试可行性
            File file = new File("C:/Users/issuser/Pictures/Camera Roll/640.gif");
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[(int) file.length()];
            fis.read(buffer);
            fis.close();

            ChannelSftp channel = (ChannelSftp) session.openChannel(UploadConstants.UPLOAD_SFTP);
            channel.connect();
//            channel.cd("/mydata/myfile/useFile");
            channel.cd(uploadServer.getUseFilePath());
            channel.put(new ByteArrayInputStream(buffer), "xxx.gif");
            channel.disconnect();

            // 断开连接
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上传linux服务器失败 >>>" + e.getMessage());
        }
    }

    /**
     * 前端文件转 base64，然受再上传到服务器
     * @param uploadServer
     * @throws Exception
     */
    public static void testUploadDebug(UploadServer uploadServer) throws Exception{
        try {
            JSch jsch = new JSch();
            // 根据用户名，主机ip，端口获取一个session对象
            Session session = jsch.getSession(uploadServer.getUser(), uploadServer.getHost(), uploadServer.getPort());
            session.setPassword("root");// 设置密码
            /**”如果设置成“yes”，ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件，
             并且一旦计算机的密匙发生了变化，就拒绝连接。 */
            session.setConfig("StrictHostKeyChecking", "no");
//        Properties config = new Properties();
//        config.put("StrictHostKeyChecking", "no");
//        session.setConfig(config);

            // 设置超时时间  10s
            session.setTimeout(10000);
            // 建立连接
            session.connect();

            // 创建一个存放 正在使用的文件目录
            Channel channel0 = session.openChannel(UploadConstants.UPLOAD_EXEC);
            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel0).setCommand("mkdir -p /mydata/myfile/useFile");
            ((ChannelExec) channel0).setCommand("mkdir -p " + uploadServer.getUseFilePath());
            channel0.connect();
            channel0.disconnect();

            // 创建一个存放 正在使用的文件目录
            // 后面可直接执行删除命令处理，目前先熟悉各种操作
//            Channel channel1 = session.openChannel(UploadConstants.UPLOAD_EXEC);
//            // 优化，这个可以再加一层管控， 比如根据系统区分，再加一层目录
//            ((ChannelExec) channel1).setCommand("mkdir -p /mydata/myfile/nouseFile");
//            channel0.connect();
//            channel0.disconnect();

            // 上传文件操作
            UploadFile uploadFile = uploadServer.getFileList().get(0);
//            String base64String = uploadServer.getFileList().get(0).getBase64FileInfo();
//            String suffix = uploadServer.getFileList().get(0).getSuffix();;
            File file = base64ToFile(uploadFile);
            FileInputStream fis = new FileInputStream(base64ToFile(uploadFile));
            byte[] buffer = new byte[(int) file.length()];
            fis.read(buffer);
            fis.close();

            ChannelSftp channel = (ChannelSftp) session.openChannel(UploadConstants.UPLOAD_SFTP);
            channel.connect();
//            channel.cd("/mydata/myfile/useFile");
            channel.cd(uploadServer.getUseFilePath());
            channel.put(new ByteArrayInputStream(buffer), UUID.randomUUID() + uploadFile.getSuffix());
            channel.disconnect();

            // 断开连接
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上传linux服务器失败 >>>" + e.getMessage());
        }
    }

    /**
     * base64文件信息转 file
     * @param uploadFile
     * @return
     */
    public static File base64ToFile(UploadFile uploadFile) {
        // 指定本地文件目录
        String directoryPath = "C:\\Users\\xulei\\Desktop\\localFiles\\pics";
        // 创建file对象
        File directory = new File(directoryPath);
        // 文件目录不存在就创建目录
        if(!directory.exists()) {
            directory.mkdirs();
        }

        String fileName = directoryPath + "\\" + UUID.randomUUID() + uploadFile.getSuffix();
        File file = new File(fileName);

        try {
            String base64FileInfo = uploadFile.getBase64FileInfo();
            if(base64FileInfo.indexOf(",") != -1) {
                base64FileInfo = base64FileInfo.substring(base64FileInfo.indexOf(",")+1);
            }
            byte[] bytes = Base64.getDecoder().decode(base64FileInfo);
            FileOutputStream out = new FileOutputStream(file);
            out.write(bytes);
            out.close();
            System.out.println("创建文件成功");
        } catch (Exception e) {
            System.out.println("创建文件出错");
        }

        return file;
    }


    /**
     * MultipartFile 转 file
     * @param file
     * @return
     * @throws IOException
     */
    public static File convertMultipartFileToFile(MultipartFile file) throws IOException {
        File convFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            System.out.println("File is empty or its size is zero, please check!");
        } else {
            InputStream inputStream = file.getInputStream();
            convFile = new File(file.getOriginalFilename());
            FileOutputStream fos = new FileOutputStream(convFile);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            fos.close();
            inputStream.close();
        }
        return convFile;
    }

    /** todo: 文件上传到搭建的虚拟机 *********end*********** */
}
